home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2007 December / PCWKCD1207B.iso / Blogowanie poza sfera / Flock 0.9.1.3 stable / flock-0.9.1.3.en-US.win32.exe / flock / components / flockXangaService.js < prev    next >
Text File  |  2007-10-12  |  19KB  |  562 lines

  1. // vim: ts=2 sw=2 expandtab cindent
  2. // BEGIN FLOCK GPL
  3. // 
  4. // Copyright Flock Inc. 2005-2007
  5. // http://flock.com
  6. // 
  7. // This file may be used under the terms of of the
  8. // GNU General Public License Version 2 or later (the "GPL"),
  9. // http://www.gnu.org/licenses/gpl.html
  10. // 
  11. // Software distributed under the License is distributed on an "AS IS" basis,
  12. // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. // for the specific language governing rights and limitations under the
  14. // License.
  15. // 
  16. // END FLOCK GPL
  17. //
  18.  
  19. const ENABLE_DEBUG = true; // switch to turn off slow debug code for production
  20. function DEBUG(x) { if (ENABLE_DEBUG) debug("flockXangaService: "+x+"\n"); }
  21.  
  22. const Cc = Components.classes;
  23. const Ci = Components.interfaces;
  24. const Cr = Components.results;
  25.  
  26. const XANGA_CID = Components.ID("{4a67cc66-aafa-4df6-a836-c63bc92651e7}");
  27. const XANGA_CONTRACTID = "@flock.com/people/xanga;1";
  28. const XANGA_FAVICON = "http://www.xanga.com/favicon.ico";
  29. const SERVICE_ENABLED_PREF = "flock.service.xanga.enabled";
  30. const CATEGORY_COMPONENT_NAME = "Xanga JS Component"
  31. const CATEGORY_ENTRY_NAME = "xanga"
  32.  
  33. const RDFS = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
  34.  
  35.  
  36. // ====================================================
  37. // ========== BEGIN General helper functions ==========
  38. // ====================================================
  39.  
  40. var gCompTK;
  41. function getCompTK() {
  42.   if (!gCompTK) {
  43.     gCompTK = Components.classes["@flock.com/singleton;1"]
  44.                         .getService(Components.interfaces.flockISingleton)
  45.                         .getSingleton("chrome://browser/content/flock/services/common/load-compTK.js")
  46.                         .wrappedJSObject;
  47.   }
  48.   return gCompTK;
  49. }
  50.  
  51.  
  52. function loadSubScript(spec) {
  53.   var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader);
  54.   var context = {};
  55.   loader.loadSubScript(spec, context);
  56.   return context;
  57. }
  58.  
  59. var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
  60.         .getService(Ci.mozIJSSubScriptLoader);
  61. loader.loadSubScript("chrome://browser/content/utilityOverlay.js");
  62.  
  63.  
  64. // ================================================
  65. // ========== BEGIN flockXGService class ==========
  66. // ================================================
  67.  
  68. function flockXGService()
  69. {
  70.   var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
  71.   obs.addObserver(this, "xpcom-shutdown", false);
  72.   this.status = Ci.flockIWebService.STATUS_UNKNOWN;
  73.   this.url = "http://www.xanga.com";
  74.   this.mIsInitialized = false;
  75.   this._ctk = {
  76.     interfaces: [
  77.       "nsISupports",
  78.       "nsIClassInfo",
  79.       "nsISupportsCString",
  80.       "nsIObserver",
  81.       "flockIWebService",
  82.       "flockIManageableWebService",
  83.       "flockIBlogWebService"
  84.     ],
  85.     shortName: "xanga",
  86.     fullName: "Xanga",
  87.     description: "Flock Xanga Service",
  88.     favicon: XANGA_FAVICON,
  89.     CID: XANGA_CID,
  90.     contractID: XANGA_CONTRACTID,
  91.     accountClass: flockXGAccount
  92.   };
  93.   this._profiler = Cc["@flock.com/profiler;1"].getService(Ci.flockIProfiler);
  94.   this.init();
  95. }
  96.  
  97.  
  98. // BEGIN nsIObserver
  99. flockXGService.prototype.observe =
  100. function flockXGService_observe(subject, topic, state)
  101. {
  102.   switch (topic) {
  103.     case "xpcom-shutdown":
  104.       var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
  105.       obs.removeObserver(this, "xpcom-shutdown");
  106.       return;
  107.   }
  108. }
  109. // END nsIObserver
  110.  
  111.  
  112. // BEGIN flockIWebService
  113. flockXGService.prototype.addAccountById =
  114. function flockXGService_addAccountById(aUsername, aIsTransient, aListener)
  115. {
  116.   this.logger.info("addAccountById('"+aUsername+"')");
  117.   var accountURN = this.acUtils.createAccount(this, aUsername);
  118.   var c_account = this.faves_coop.get(accountURN);
  119.   c_account.isTransient = aIsTransient;
  120.   c_account.service = this.xgService;
  121.   this.USER = accountURN;
  122.  
  123.   // add blog
  124.   var c_blog = new this.faves_coop.Blog(accountURN+":uniqueblog", {
  125.     name: aUsername,
  126.     title: aUsername,
  127.     blogid: aUsername,
  128.     apiLink: "",
  129.     URL: "http://www.xanga.com/private/yourhome.aspx?user="+aUsername,
  130.   });
  131.   c_account.children.addOnce(c_blog);
  132.  
  133.   var acct = this.getAccount(accountURN);
  134.   if (aListener) aListener.onSuccess(acct, "addAccount");
  135.   return acct;
  136. }
  137.  
  138.  
  139. flockXGService.prototype.init =
  140. function flockXGService_init()
  141. {
  142.   DEBUG(".init()");
  143.  
  144.   // Prevent re-entry
  145.   if (this.mIsInitialized) return;
  146.   this.mIsInitialized = true;
  147.  
  148.   var evtID = this._profiler.profileEventStart("xanga-init");
  149.  
  150.   this.prefService = Components.classes["@mozilla.org/preferences-service;1"]
  151.                                .getService(Components.interfaces.nsIPrefBranch);
  152.   if ( this.prefService.getPrefType(SERVICE_ENABLED_PREF) &&
  153.        !this.prefService.getBoolPref(SERVICE_ENABLED_PREF) )
  154.   {
  155.     DEBUG("Pref "+SERVICE_ENABLED_PREF+" set to FALSE... not initializing.");
  156.     var catMgr = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
  157.     catMgr.deleteCategoryEntry("wsm-startup", CATEGORY_COMPONENT_NAME, true);
  158.     catMgr.deleteCategoryEntry("flockWebService", CATEGORY_ENTRY_NAME, true);
  159.     return;
  160.   }
  161.  
  162.   // Logger
  163.   this.logger = Cc['@flock.com/logger;1'].createInstance(Ci.flockILogger);
  164.   this.logger.init("xanga");
  165.  
  166.   // Attributes of flockIBlogWebService
  167.   this.supportsCategories = 0;
  168.   this.supportsPostReplace = false;
  169.   this.metadataOverlay = "chrome://browser/content/flock/blog/xangaOverlay.xul";
  170.  
  171.   this.acUtils = Cc["@flock.com/account-utils;1"].getService(Ci.flockIAccountUtils);
  172.  
  173.   this.faves_coop = Cc['@flock.com/singleton;1'].getService(Ci.flockISingleton).getSingleton('chrome://browser/content/flock/common/load-faves-coop.js').wrappedJSObject;
  174.  
  175.   this.account_root = this.faves_coop.accounts_root;
  176.  
  177.   this.xgService = new this.faves_coop.Service('urn:xanga:service');
  178.   this.xgService.name = 'xanga';
  179.   this.xgService.desc = 'The Xanga.com Service';
  180.   this.xgService.domains = "xanga.com";
  181.   this.xgService.serviceId = XANGA_CONTRACTID;
  182.  
  183.   var xgHomepage = new this.faves_coop.Favorite('urn:xanga:actions:homepage');
  184.   xgHomepage.name = 'Xanga.com';
  185.   xgHomepage.URL = 'http://www.xanga.com';
  186.  
  187.   this.xgService.children.addOnce(xgHomepage);
  188.   this.urn = this.xgService.id();
  189.  
  190.   this.webDetective = this.acUtils.useWebDetective("xanga.xml");
  191.  
  192.   this._profiler.profileEventEnd(evtID, "");
  193. }
  194.  
  195.  
  196. flockXGService.prototype.refresh =
  197. function flockXGService_refresh(aURN, aListener)
  198. {
  199.     debug("flockXGService refresh with aURN of "+aURN+"\n");
  200.  
  201.     // Introspection against what we're syncing - Identity or Account or Item?
  202.     var refreshItem = this.faves_coop.get(aURN);
  203.  
  204.   if (refreshItem instanceof this.faves_coop.Account) {
  205.     }
  206.   else if (refreshItem instanceof this.faves_coop.Favorite) {
  207.     }
  208.   else {
  209.         throw Components.results.NS_ERROR_ABORT;
  210.     }
  211. }
  212.  
  213. flockXGService.prototype.refreshAccount =
  214. function flockXGService_refreshAccount(aURN, aListener)
  215. {
  216.   debug("XGService - refreshAccount with aURN of "+aURN);
  217. }
  218.  
  219.  
  220. // BEGIN flockIBlogWebService interface
  221.  
  222. flockXGService.prototype.newPost = function(aListener, aBlogId, aPost, aPublish, aNotifications) {
  223.   dump("==== newPost in Xanga\n");
  224. /*  var authenticated = false;
  225.   var enum = this.faves_coop.accounts_root.children.enumerate();
  226.   while (enum.hasMoreElements()) {
  227.     var account = enum.getNext();
  228.     if ((account.serviceId == XANGA_CONTRACTID) && (account.isAuthenticated))
  229.       authenticated = true;
  230.   }
  231.  
  232.   if (!authenticated) {
  233.     var error = Components.classes['@flock.com/error;1']
  234.                           .createInstance(Components.interfaces.flockIError);
  235.     error.errorCode = error.BLOG_LOGIN_REQUIRED;
  236.     aListener.onError(error);
  237.     return;
  238.   }*/
  239.  
  240.   var notifsArray = new Array();
  241.   // var html = aPost.description + addTechnoratiTags(aPost.tags);
  242.   while (aNotifications.hasMore())
  243.     notifsArray.push(aNotifications.getNext());
  244.   //var comments = aPost.extra.getNext();
  245.   //var privacy = aPost.extra.getNext();
  246.   //var mood = aPost.extra.getNext().split('||');
  247.  
  248.   var textToSubURI = Components.classes["@mozilla.org/intl/texttosuburi;1"].getService(Components.interfaces.nsITextToSubURI);
  249.   var tags = "";
  250.   while (aPost.tags.hasMore())
  251.     tags += (aPost.tags.getNext() + '%2C');
  252.   var privacy = aPost.extra.getNext();
  253.   var comments = aPost.extra.getNext();
  254.  
  255.   function postForReal(aToken) {
  256.     var postMessage = '__EVENTTARGET='+
  257.                       '&__EVENTARGUMENT='+
  258.                       '&__VIEWSTATE=' + aToken +
  259.                       '&txtTitle=' + textToSubURI.ConvertAndEscape("UTF-8", aPost.title) +
  260.                       '&spellcheckbtn=false' +
  261.                       '&RadEContentTextareawerichtext=' +
  262.                       '&werichtext=++++++++++++++++++++++++++++++++++++++++++++++++' +
  263.                       '&tnames=' +
  264.                       '&ptag=tagname' +
  265.                       '&proftitle0=' +
  266.                       '&proftitle1=' +
  267.                       '&proftitle3=' +
  268.                       '&xztitle1=' +
  269.                       '&xztitle2=' +
  270.                       '&xzasin1=' +
  271.                       '&xzformat=' +
  272.                       '&xzextravalue=' +
  273.                       '&weprivacy=' + privacy
  274.                       '&txtRating=';
  275.     if (comments == "on")
  276.       postMessage += '&chkComments=on';
  277.     postMessage += '&btnSave=Save+Changes' +
  278.                       '&epropcurrstate=0' +
  279.                       '&commentcnt=0' +
  280.                       '&weuniqueid=0' +
  281.                       '&webgcolor=' +
  282.                       '&webdcolor=' +
  283.                       '&tprefid=29385413' +
  284.                       '&tpref2=' +
  285.                       '&tpref3=' +
  286.                       '&tpref4=' +
  287.                       '&tpref5=' +
  288.                       '&cncel=' +
  289.                       '&postvalues=' +
  290.                       '&photovalues=' +
  291.                       '&videovalues=' +
  292.                       '&audiovalues=' +
  293.                       '&bodyvalue=' + textToSubURI.ConvertAndEscape("UTF-8", aPost.description.replace(/\n/g, "<br/>")) +
  294.                       '&mediaargs=' +
  295.                       '&tagsoriginal=' +
  296.                       '&tagstodelete=%2C' +
  297.                       '&tagstoadd=%2C' + tags;
  298.  
  299.     var xhr2 = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance (Ci.nsIXMLHttpRequest);
  300.     xhr2.open ('POST', 'http://www.xanga.com/private/editorx.aspx', true);
  301.     xhr2.setRequestHeader ('Content-Type', 'application/x-www-form-urlencoded');
  302.     xhr2.setRequestHeader ('Content-Length', postMessage.length );
  303.     xhr2.setRequestHeader ('Referer', 'http://www.xanga.com/private/editorx.aspx');
  304.  
  305.     xhr2.onreadystatechange = function (aEvent) {
  306.       debug("readyState: "+xhr2.readyState);
  307.       if (xhr2.readyState == 4) {
  308.         debug("status: "+xhr2.status);
  309.         if ((xhr2.status != 200) && (xhr2.status != 302)) {
  310.           aListener.onError (xhr2.statusText);
  311.           return;
  312.         }
  313.         debug(xhr2.responseText);
  314.         aListener.onResult("");
  315.       }
  316.     }
  317.  
  318.     dump(" *** Post FOR REAL!!...\n");
  319.  
  320.     //dump(postMessage);
  321.     xhr2.send(postMessage);
  322.   }
  323.  
  324.   function getViewState() {
  325.     // Show the editor to get the "viewState" token
  326.     var xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
  327.     xhr.open('GET', 'http://www.xanga.com/private/editorx.aspx', true);
  328.     xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  329.  
  330.     xhr.onreadystatechange = function (aEvent) {
  331.       if (xhr.readyState == 4) {
  332.         if (xhr.status != 200) {
  333.           aListener.onError (xhr.statusText);
  334.           return;
  335.         }
  336.         //dump(xhr.responseText);
  337.  
  338.         if (xhr.responseText.match("PLEASE SIGN IN")) {
  339.           var error = Components.classes['@flock.com/error;1']
  340.                           .createInstance(Ci.flockIError);
  341.           error.errorCode = error.BLOG_LOGIN_REQUIRED;
  342.           aListener.onError(error);
  343.           return;
  344.         }
  345.         // Get the token and post for real
  346.         var theHash = xhr.responseText.match(/(?:id\=\"\__VIEWSTATE\"\svalue\=\")(.+)(?=\")/);
  347.         debug("theHash: "+theHash+"\n");
  348.         debug("theHash[1]: "+theHash[1]+"\n");
  349.  
  350.         if (theHash != null){
  351.           var token = theHash[1];
  352.           debug("*****\n*****\n TOKEN: "+token+"\n");
  353.           postForReal(token);
  354.         }
  355.       }
  356.     }
  357.     xhr.send(null);
  358.   }
  359.  
  360.   getViewState();
  361. }
  362.  
  363. flockXGService.prototype.editPost = function(aListener, aBlogId, aPost, aPublish, atomid, editURI, aNotifications){
  364. }
  365.  
  366. flockXGService.prototype.deletePost = function(aListener, aBlogId, aPostid){
  367. }
  368.  
  369. flockXGService.prototype.getUsersBlogs = function(aListener, aAccount){
  370. }
  371.  
  372. flockXGService.prototype.getRecentPosts = function(aListener, aBlogId, aNumber){
  373. }
  374.  
  375. flockXGService.prototype.getCategoryList = function(aListener, aBlogId){
  376. }
  377. // END flockIBlogWebService interface
  378.  
  379.  
  380. // BEGIN flockIManageableWebService interface
  381. flockXGService.prototype.getAccountIDFromDocument =
  382. function flockXGService_getAccountIDFromDocument(aDocument)
  383. {
  384.   this.logger.debug("{flockIManageableWebService}.getAccountIDFromDocument(aDocument)");
  385.   aDocument.QueryInterface(Ci.nsIDOMHTMLDocument);
  386.  
  387.   var results = Cc["@mozilla.org/hash-property-bag;1"].createInstance(Ci.nsIWritablePropertyBag2);
  388.   dump("Let's find what Xanga user it is\n");
  389.   if (this.webDetective.detect("xanga", "accountinfo", aDocument, results)) {
  390.     var accountID = results.getPropertyAsAString("accountid");
  391.     dump(accountID+" it is!\n");
  392.     if (accountID && accountID.length) {
  393.       return accountID;
  394.     }
  395.   }
  396.   else {
  397.     dump("I don't know :(\n");
  398.   }
  399.  
  400.   return null;
  401.  
  402. /*  var title = aDocument.title;
  403.   debug(title);
  404.   if (title.match(/(.+)\'s\sXanga\sSite/)) {
  405.     var val = RegExp.$1;
  406.     this.logger.debug(" - found account ID: "+val);
  407.     return val;
  408.   } else
  409.     debug("Xanga: unable to find the username from the page.\n");
  410.  
  411.   return null;*/
  412. }
  413.  
  414. flockXGService.prototype.updateAccountStatusFromDocument =
  415. function flockXGService_updateAccountStatusFromDocument(aDocument)
  416. {
  417.   this.logger.debug("{flockIManageableWebService}.updateAccountStatusFromDocument(aDocument)");
  418.   if (this.webDetective.detect("xanga", "loggedin", aDocument, null)) {
  419.     debug("WOOT WOOT Xanga user logged IN!\n");
  420.     var accountID = this.getAccountIDFromDocument(aDocument);
  421.     var acctURN = this.acUtils.getAccountURNById(this.urn, accountID);
  422.  
  423.       var avatarURL;
  424.       var results = Cc["@mozilla.org/hash-property-bag;1"].createInstance(Ci.nsIWritablePropertyBag2);
  425.  
  426.       if(this.webDetective.detect("xanga", "avatarURLDetect", aDocument, results)) {
  427.         try {
  428.           avatarURL = results.getPropertyAsAString("avatarURL");
  429.         } catch(e) {
  430.           // No avatar found
  431.         }
  432.       }
  433.  
  434.       var acctURN = this.acUtils.getAccountURNById(this.urn, accountID);
  435.       var acct = this.faves_coop.get(acctURN);
  436.       acct.avatar = avatarURL;
  437.  
  438.     var accounts = this.faves_coop.Account.find({serviceId: XANGA_CONTRACTID});
  439.     for (var i = 0; i < accounts.length; i++) {
  440.       if (accounts[i].id() == acctURN) {
  441.         accounts[i].isAuthenticated = true;
  442.       } else {
  443.         accounts[i].isAuthenticated = false;
  444.       }
  445.     }
  446.   } else if (this.webDetective.detect("xanga", "loggedout", aDocument, null)) {
  447.     debug("WOOT WOOT Xanga user logged OUT!\n");
  448.     this.acUtils.markAllAccountsAsLoggedOut(XANGA_CONTRACTID);
  449.   }
  450. }
  451. // END flockIManageableWebService interface
  452.  
  453.  
  454.  
  455. // ================================================
  456. // ========== BEGIN XPCOM Module support ==========
  457. // ================================================
  458.  
  459. function createModule(aParams) {
  460.   return {
  461.     registerSelf: function (aCompMgr, aFileSpec, aLocation, aType) {
  462.       var aCompMgr = aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
  463.       aCompMgr.registerFactoryLocation( aParams.CID, aParams.componentName,
  464.                                         aParams.contractID, aFileSpec,
  465.                                         aLocation, aType );
  466.       var catMgr = Cc["@mozilla.org/categorymanager;1"]
  467.         .getService(Ci.nsICategoryManager);
  468.       if (!aParams.categories) { aParams.categories = []; }
  469.       for (var i = 0; i < aParams.categories.length; i++) {
  470.         var cat = aParams.categories[i];
  471.         catMgr.addCategoryEntry( cat.category, cat.entry,
  472.                                  cat.value, true, true );
  473.       }
  474.     },
  475.     getClassObject: function (aCompMgr, aCID, aIID) {
  476.       if (!aCID.equals(aParams.CID)) { throw Cr.NS_ERROR_NO_INTERFACE; }
  477.       if (!aIID.equals(Ci.nsIFactory)) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; }
  478.       return { // Factory
  479.         createInstance: function (aOuter, aIID) {
  480.           if (aOuter != null) { throw Cr.NS_ERROR_NO_AGGREGATION; }
  481.           var comp = new aParams.componentClass();
  482.           if (aParams.implementationFunc) { aParams.implementationFunc(comp); }
  483.           return comp.QueryInterface(aIID);
  484.         }
  485.       };
  486.     },
  487.     canUnload: function (aCompMgr) { return true; }
  488.   };
  489. }
  490.  
  491. // NS Module entrypoint
  492. function NSGetModule(aCompMgr, aFileSpec) {
  493.   return createModule({
  494.     componentClass: flockXGService,
  495.     CID: XANGA_CID,
  496.     contractID: XANGA_CONTRACTID,
  497.     componentName: CATEGORY_COMPONENT_NAME,
  498.     implementationFunc: function (aComp) { getCompTK().addAllInterfaces(aComp); },
  499.     categories: [
  500.       { category: "wsm-startup", entry: CATEGORY_COMPONENT_NAME, value: XANGA_CONTRACTID },
  501.       { category: "flockWebService", entry: CATEGORY_ENTRY_NAME, value: XANGA_CONTRACTID }
  502.     ]
  503.   });
  504. }
  505.  
  506. // ========== END XPCOM Module support ==========
  507.  
  508.  
  509.  
  510. // ================================================
  511. // ========== BEGIN flockXGAccount class ==========
  512. // ================================================
  513.  
  514.  
  515. function flockXGAccount()
  516. {
  517.   this.logger = Cc["@flock.com/logger;1"].createInstance(Ci.flockILogger);
  518.   this.logger.init("xangaAccount");
  519.   this.faves_coop = Cc["@flock.com/singleton;1"].getService(Ci.flockISingleton)
  520.       .getSingleton("chrome://browser/content/flock/common/load-faves-coop.js")
  521.       .wrappedJSObject;
  522.   this.acUtils = Cc["@flock.com/account-utils;1"].getService(Ci.flockIAccountUtils);
  523.   this._ctk = {
  524.     interfaces: [
  525.       "nsISupports",
  526.       "flockIWebServiceAccount",
  527.       "flockIBlogWebServiceAccount"
  528.     ]
  529.   };
  530.   getCompTK().addAllInterfaces(this);
  531. }
  532.  
  533.  
  534. // BEGIN flockIWebServiceAccount
  535. flockXGAccount.prototype.activate = function(aListener) {
  536. }
  537. flockXGAccount.prototype.deactivate = function(aListener) {
  538. }
  539. // END flockIWebServiceAccount
  540.  
  541.  
  542. // flockIBlogWebServiceAccount implementation
  543. flockXGAccount.prototype.getBlogs = function() {
  544.   this.logger.info("{flockIBlogWebServiceAccount}.getBlogs()");
  545.   var blogsEnum = {
  546.     QueryInterface : function(iid) {
  547.       if (!iid.equals(Ci.nsISupports) &&
  548.           !iid.equals(Ci.nsISimpleEnumerator))
  549.       {
  550.         throw Components.results.NS_ERROR_NO_INTERFACE;
  551.       }
  552.       return this;
  553.     },
  554.     hasMoreElements : function() {
  555.       return false;
  556.     },
  557.     getNext : function() {
  558.     }
  559.   };
  560.   return blogsEnum;
  561. }
  562.